package wowraidmanager.client.flowlist;

import java.util.ArrayList;
import java.util.List;

import wowraidmanager.client.flowlist.utils.ErrorCheck;
import wowraidmanager.client.service.flowlist.FlowlistService;
import wowraidmanager.client.service.flowlist.FlowlistServiceAsync;
import wowraidmanager.shared.model.flowlist.Flowlist;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.HasHorizontalAlignment;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.RadioButton;
import com.google.gwt.user.client.ui.TextArea;
import com.google.gwt.user.client.ui.Widget;

public class Index extends Composite{

    private static FlowlistUiBinder uiBinder = GWT.create(FlowlistUiBinder.class);

    FlowlistServiceAsync flowlistService = GWT.create(FlowlistService.class);

    private static ErrorCheck errorCheck = new ErrorCheck();

    interface FlowlistUiBinder extends UiBinder<Widget, Index>{
    }

    static int COLUMN_FLOWNUMBER = 0;
    static int COLUMN_ATTEND = 1;
    static int COLUMN_FLOW = 2;
    static int COLUMN_ABSENCE = 3;
    static int COLUMN_NAME = 4;

    static String SPEC_DPS = "DPS";
    static String SPEC_HEAL = "HEAL";
    static String SPEC_TANK = "TANK";

    RadioButton attendRadioArray;
    RadioButton flowRadioArray;
    RadioButton absenceRadioArray;

    ArrayList<Flowlist> dpsFlow;
    ArrayList<Flowlist> healFlow;
    ArrayList<Flowlist> tankFlow;

    @UiField
    Label errorString;

    @UiField
    FlexTable flowlist_DPS;

    @UiField
    FlexTable flowlist_HEAL;

    @UiField
    FlexTable flowlist_TANK;

    @UiField
    PasswordTextBox password;

    @UiField
    Button nextFlow_DPS;

    @UiField
    Button nextFlow_HEAL;

    @UiField
    Button nextFlow_TANK;

    @UiField
    Button previewFlow_DPS;

    @UiField
    Button previewFlow_HEAL;

    @UiField
    Button previewFlow_TANK;

    @UiField
    Button newFlow_DPS;

    @UiField
    Button newFlow_HEAL;

    @UiField
    Button newFlow_TANK;

    @UiField
    TextArea playerNames_DPS;

    @UiField
    TextArea playerNames_HEAL;

    @UiField
    TextArea playerNames_TANK;

    public Index(){
        initWidget(uiBinder.createAndBindUi(this));
        getflowlist();
    }

    @UiHandler({"nextFlow_DPS", "nextFlow_HEAL", "nextFlow_TANK", "previewFlow_DPS", "previewFlow_HEAL", "previewFlow_TANK", "newFlow_DPS", "newFlow_HEAL", "newFlow_TANK"})
    void handleClick(ClickEvent e){

        String errorMessage = errorCheck.checkPassword(password.getText());

        if(errorMessage.equals("")){
            if(e.getSource() == nextFlow_DPS){
                errorMessage = nextFlow(dpsFlow, flowlist_DPS, playerNames_DPS, SPEC_DPS);
            }else if(e.getSource() == nextFlow_HEAL){
                errorMessage = nextFlow(healFlow, flowlist_HEAL, playerNames_HEAL, "HEAL");
            }else if(e.getSource() == nextFlow_TANK){
                errorMessage = nextFlow(tankFlow, flowlist_TANK, playerNames_TANK, "TANK");
            }else if(e.getSource() == previewFlow_DPS){
                previewFlow(dpsFlow, flowlist_DPS, playerNames_DPS, SPEC_DPS);
            }else if(e.getSource() == previewFlow_HEAL){
                previewFlow(healFlow, flowlist_HEAL, playerNames_HEAL, "HEAL");
            }else if(e.getSource() == previewFlow_TANK){
                previewFlow(tankFlow, flowlist_TANK, playerNames_TANK, "TANK");
            }else if(e.getSource() == newFlow_DPS){
                newFlow(flowlist_DPS, playerNames_DPS, SPEC_DPS);
            }else if(e.getSource() == newFlow_HEAL){
                newFlow(flowlist_HEAL, playerNames_HEAL, "HEAL");
            }else if(e.getSource() == newFlow_TANK){
                newFlow(flowlist_TANK, playerNames_TANK, "TANK");
            }
        }

        errorString.setText(errorMessage);
    }

    private String nextFlow(ArrayList<Flowlist> flowlist, FlexTable flowlistTable, TextArea playerNames, String role){
        String errorMessage = "";
        int radioRow = flowlistTable.getRowCount() - 2;
        ArrayList<String> attendRadioArray = getRadioArray(flowlistTable, COLUMN_ATTEND);
        ArrayList<String> flowRadiokArray = getRadioArray(flowlistTable, COLUMN_FLOW);
        ArrayList<String> stayRadioArray = getRadioArray(flowlistTable, COLUMN_ABSENCE);

        errorMessage = errorCheck.checkflowstay(attendRadioArray, flowRadiokArray, stayRadioArray, role, radioRow);

        if(errorMessage.equals("")){
            setNextflowlist(flowlist, flowRadiokArray, stayRadioArray, role, flowlistTable, playerNames);
        }
        return errorMessage;
    }

    private void setNextflowlist(ArrayList<Flowlist> flowlist, final ArrayList<String> flowCheckArray, final ArrayList<String> stayCheckArray, final String role, final FlexTable flowlistTable, final TextArea playerNames){

        String[] tempflownumber = new String[flowlist.size()];

        for(int i = 0;i < tempflownumber.length;i++){
            String number = String.valueOf(i + 1);
            if(flowCheckArray != null && flowCheckArray.contains(number)){
                tempflownumber[i] = null;
            }else if(stayCheckArray != null && stayCheckArray.contains(number)){
                tempflownumber[i] = number;
            }else{
                for(int j = 0;j < tempflownumber.length;j++){
                    if(tempflownumber[j] == null){
                        tempflownumber[j] = number;
                        break;
                    }
                }
            }
        }

        if(flowCheckArray != null){
            for(String flowNumber:flowCheckArray){
                for(int i = 0;i < tempflownumber.length;i++){
                    if(tempflownumber[i] == null){
                        tempflownumber[i] = flowNumber;
                        break;
                    }
                }
            }
        }

        for(Flowlist newFlowlist:flowlist){
            int currentNumber = newFlowlist.getCurrentFlowNumber();
            newFlowlist.setPreviewFlowNumber(currentNumber);

            for(int i = 0;i < tempflownumber.length;i++){
                if(currentNumber == Integer.valueOf(tempflownumber[i])){
                    newFlowlist.setCurrentFlowNumber(i + 1);
                    break;
                }
            }
        }

        setflowlist(flowlist, flowlistTable, playerNames, role);
    }

    private ArrayList<String> getRadioArray(FlexTable flowlistTable, int column){
        ArrayList<String> radioArray = new ArrayList<String>();
        RadioButton radioButton;
        for(int i = 2;i < flowlistTable.getRowCount();i++){
            radioButton = (RadioButton)flowlistTable.getWidget(i, column);
            if(radioButton.getValue()){
                radioArray.add(radioButton.getFormValue());
            }
        }
        return radioArray;
    }

    private void previewFlow(ArrayList<Flowlist> flowlist, FlexTable flowlistTable, TextArea playerNames, String role){
        setPreviewflowlist(flowlist, role, flowlistTable, playerNames);
        setFlowlist(role);
    }

    private void newFlow(FlexTable flowlistTable, TextArea playerNames, String role){
        String[] playernameList = playerNames.getText().trim().split("\n");
        ArrayList<Flowlist> newListFlowlist = new ArrayList<Flowlist>();

        deleteRole(role);
        for(int i = 0;i < playernameList.length;i++){
            Flowlist newflowlist = new Flowlist();
            newflowlist.setPlayerName(playernameList[i]);
            newflowlist.setCurrentFlowNumber(i + 1);
            newflowlist.setPreviewFlowNumber(i + 1);
            newflowlist.setSpec(role);

            newListFlowlist.add(newflowlist);
        }
        setflowlist(newListFlowlist, flowlistTable, playerNames, role);
    }

    private void setPreviewflowlist(ArrayList<Flowlist> flowlist, final String role, final FlexTable flowlistTable, final TextArea playerNames){

        // TODO 自動生成されたメソッド・スタブ
        for(int i = 0;i < flowlist.size();i++){
            Flowlist newFlowlist = flowlist.get(i);
            newFlowlist.setCurrentFlowNumber(newFlowlist.getPreviewFlowNumber());
            flowlist.set(i, newFlowlist);
        }

        setflowlist(flowlist, flowlistTable, playerNames, role);

    }

    private void getflowlist(){
        flowlistService.getflowlist(new AsyncCallback<ArrayList<Flowlist>>(){

            public void onSuccess(ArrayList<Flowlist> result){
                splitFlowlist(result);
            }

            public void onFailure(Throwable caught){
                Window.alert(caught.getMessage());
            }
        });
    }

    protected void splitFlowlist(ArrayList<Flowlist> result){
        dpsFlow = getFlowlist(result, SPEC_DPS);
        healFlow = getFlowlist(result, SPEC_HEAL);
        tankFlow = getFlowlist(result, SPEC_TANK);

        setFlowlist(SPEC_DPS);
        setFlowlist(SPEC_HEAL);
        setFlowlist(SPEC_TANK);
    }

    private void setFlowlist(String role){

        if(role.equals(SPEC_DPS)){
            setTable(dpsFlow, flowlist_DPS, SPEC_DPS);
            setPlayerName(dpsFlow, playerNames_DPS);
        }else if(role.equals(SPEC_HEAL)){
            setTable(healFlow, flowlist_HEAL, SPEC_HEAL);
            setPlayerName(healFlow, playerNames_HEAL);
        }else if(role.equals(SPEC_TANK)){
            setTable(tankFlow, flowlist_TANK, SPEC_TANK);
            setPlayerName(tankFlow, playerNames_TANK);
        }
    }

    private ArrayList<Flowlist> getFlowlist(ArrayList<Flowlist> result, String role){
        ArrayList<Flowlist> splitFlowlist = new ArrayList<Flowlist>();
        for(Flowlist flowlist:result){
            if(flowlist.getSpec().equals(role)){
                splitFlowlist.add(flowlist);
            }
        }

        return splitFlowlist;
    }

    protected void setPlayerName(List<Flowlist> result, TextArea playerNames){
        String playerName = "";
        for(Flowlist flowlist:result){
            playerName += flowlist.getPlayerName() + "\n";
        }
        playerNames.setText(playerName);
    }

    protected void setTable(List<Flowlist> result, FlexTable flowlistTable, String role){
        flowlistTable.removeAllRows();
        flowlistTable.setBorderWidth(1);
        flowlistTable.setText(0, 0, role);
        flowlistTable.getFlexCellFormatter().setColSpan(0, 0, 5);
        flowlistTable.setText(1, COLUMN_FLOWNUMBER, "順番");
        flowlistTable.setText(1, COLUMN_ATTEND, "出席");
        flowlistTable.setText(1, COLUMN_FLOW, "フロー");
        flowlistTable.setText(1, COLUMN_ABSENCE, "欠席");
        flowlistTable.setText(1, COLUMN_NAME, "名前");
        flowlistTable.getFlexCellFormatter().setHorizontalAlignment(1, COLUMN_FLOWNUMBER, HasHorizontalAlignment.ALIGN_CENTER);
        flowlistTable.getFlexCellFormatter().setHorizontalAlignment(1, COLUMN_ATTEND, HasHorizontalAlignment.ALIGN_CENTER);
        flowlistTable.getFlexCellFormatter().setHorizontalAlignment(1, COLUMN_FLOW, HasHorizontalAlignment.ALIGN_CENTER);
        flowlistTable.getFlexCellFormatter().setHorizontalAlignment(1, COLUMN_ABSENCE, HasHorizontalAlignment.ALIGN_CENTER);
        flowlistTable.getFlexCellFormatter().setHorizontalAlignment(1, COLUMN_NAME, HasHorizontalAlignment.ALIGN_CENTER);

        int row = 2;
        for(Flowlist flowlist:result){
            attendRadioArray = new RadioButton(flowlist.getSpec() + flowlist.getCurrentFlowNumber());
            flowRadioArray = new RadioButton(flowlist.getSpec() + flowlist.getCurrentFlowNumber());
            absenceRadioArray = new RadioButton(flowlist.getSpec() + flowlist.getCurrentFlowNumber());
            attendRadioArray.setFormValue(String.valueOf(flowlist.getCurrentFlowNumber()));
            flowRadioArray.setFormValue(String.valueOf(flowlist.getCurrentFlowNumber()));
            absenceRadioArray.setFormValue(String.valueOf(flowlist.getCurrentFlowNumber()));

            flowlistTable.setText(row, COLUMN_FLOWNUMBER, String.valueOf(flowlist.getCurrentFlowNumber()));
            flowlistTable.setWidget(row, COLUMN_ATTEND, attendRadioArray);
            flowlistTable.setWidget(row, COLUMN_FLOW, flowRadioArray);
            flowlistTable.setWidget(row, COLUMN_ABSENCE, absenceRadioArray);
            flowlistTable.setText(row, COLUMN_NAME, flowlist.getPlayerName());

            flowlistTable.getFlexCellFormatter().setHorizontalAlignment(row, COLUMN_FLOWNUMBER, HasHorizontalAlignment.ALIGN_CENTER);
            flowlistTable.getFlexCellFormatter().setHorizontalAlignment(row, COLUMN_ATTEND, HasHorizontalAlignment.ALIGN_CENTER);
            flowlistTable.getFlexCellFormatter().setHorizontalAlignment(row, COLUMN_FLOW, HasHorizontalAlignment.ALIGN_CENTER);
            flowlistTable.getFlexCellFormatter().setHorizontalAlignment(row, COLUMN_ABSENCE, HasHorizontalAlignment.ALIGN_CENTER);
            flowlistTable.getFlexCellFormatter().setHorizontalAlignment(row, COLUMN_NAME, HasHorizontalAlignment.ALIGN_CENTER);

            row++;
        }
    }

    private void deleteRole(String role){
        flowlistService.deleteRole(role, new AsyncCallback<Void>(){

            public void onSuccess(Void result){
                // TODO 自動生成されたメソッド・スタブ

            }

            public void onFailure(Throwable caught){
                Window.alert(caught.getMessage());
            }

        });
    }

    private void setflowlist(ArrayList<Flowlist> flowlist, final FlexTable flowlistTable, final TextArea playerNames, final String role){
        flowlistService.setflowlist(flowlist, role, new AsyncCallback<ArrayList<Flowlist>>(){

            public void onSuccess(ArrayList<Flowlist> result){
                setsplitFlowlist(result, role);
                setFlowlist(role);
            }

            public void onFailure(Throwable caught){
                // TODO 自動生成されたメソッド・スタブ

            }
        });

    }

    protected void setsplitFlowlist(ArrayList<Flowlist> result, String role){
        if(role.equals(SPEC_DPS)){
            dpsFlow = result;
        }else if(role.equals(SPEC_HEAL)){
            healFlow = result;
        }else if(role.equals(SPEC_TANK)){
            tankFlow = result;
        }

    }
}
